package controller;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import java.util.Scanner;

import model.*;

/**
 * Makes saving and loading of the simulation to and from the hard disk possible.
 * 
 * @author Jord de Jong
 * @version 2014.02.03
 */

public class SaveLoad {
	
	/**
	 * Saves the simulation to a .svk file.
	 * @param location The location of the file to be saved to.
	 * @param simul The simulator object.
	 */
	public static void save(String location, Simulator simul) {
		try {
			File file = new File(location + ".svk");
			file.createNewFile();
			
			PrintWriter out = new PrintWriter(file);
			Field field = simul.getField();
			
			out.format("%d %d\n", field.getDepth(), field.getWidth());
			out.flush();
			
			for(int row = 0; row < field.getDepth(); row++){
				for(int col = 0; col < field.getWidth(); col++){
					Object o = field.getObjectAt(row, col);
					if(o!=null){
						out.println(o.toString());
						
						if(o instanceof Animal) {
							Animal animal = (Animal) o;
							out.format("%d %b %d %d\n", animal.getAge(), animal.getSick(), animal.getSickCounter(), animal.getFoodLevel());
							if(o instanceof Rabbit) {
								out.println(((Rabbit)o).canGetSick());
							}
						}
					} else {
						out.println("null");
					}
					
					o = field.getModifierAt(row, col);
					if(o!=null) {
						out.println(o.toString());
					} else {
						out.println("null");
					}
				}
			}
			Animal[] animals = {new Rabbit(), new Bear(), new Fox(), new Wolf()};
			for(Animal animal : animals){
				out.format("%d %d %d %d\n", animal.getMaxAge(), animal.getBreedingAge(), (int)(animal.getBreedingProbability()*100), animal.getMaxLitterSize());
			}
			out.println(simul.getStep());
			
			out.flush();
			out.close();
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * Loads a simulation from a .svk file.
	 * @param location The location of the file to be loaded from.
	 * @param simul The simulator object.
	 */
	public static void load(String location, Simulator simul, List<Actor> actors) {
		try {
			File file = new File(location + ".svk");
			file.createNewFile();
			Scanner in = new Scanner(file);
			
			actors.clear();
			int depth = in.nextInt();
			int width = in.nextInt();
			in.nextLine();
			Field field = new Field(depth, width);
			simul.setField(field);
			
			for(int row = 0; row < field.getDepth(); row++){
				for(int col = 0; col < field.getWidth(); col++){
					String type = in.nextLine();
					int age = 0;
					boolean sick = false;
					int sickCounter = 0;
					int foodLevel = 1;
					if(!type.equals("null") && !type.equals("Hunter")){
						age = in.nextInt();
						sick = in.nextBoolean();
						sickCounter = in.nextInt();
						foodLevel = in.nextInt();
						in.nextLine();
					}
					
					Actor animal = null;
					switch(type) {
					case "Rabbit" :
						boolean cgs = in.nextBoolean();
						in.nextLine();
						animal = new Rabbit(age, simul.getField(), new Location(row, col), cgs);
						break;
					case "Fox" :
						animal = new Fox(false, simul.getField(), new Location(row, col));
						break;
					case "Wolf" :
						animal = new Wolf(false, simul.getField(), new Location(row, col));
						break;
					case "Bear" : 
						animal = new Bear(false, simul.getField(), new Location(row, col));
						break;
					case "Hunter" : 
						animal = new Hunter(simul.getField(), new Location(row, col));
						break;
					}
					if(animal instanceof Animal) {
						Animal ani = (Animal)animal;
						ani.setAge(age);
						ani.setSick(sick);
						ani.setSickCounter(sickCounter);
						ani.setFoodLevel(foodLevel);
					}
					if(animal instanceof Actor) {
	            		actors.add(animal);
					}
					
					type = in.nextLine();
					switch(type) {
					case "Grass" :
						ModifierGrass grass = new ModifierGrass(true, simul.getField(), new Location(row, col));
						// age setten ofzo...
						break;
					case "Road" :
						new ModifierRoad(simul.getField(), new Location(row, col));
						break;
					}
				}
			}
			
			Animal[] animals = {new Rabbit(), new Bear(), new Fox(), new Wolf()};
			for(Animal animal : animals){
				animal.setMaxAge(in.nextInt());
				animal.setBreedingAge(in.nextInt());
				animal.setBreedingProbability(((double)in.nextInt())/100.0);
				animal.setMaxLitterSize(in.nextInt());
				in.nextLine();
			}
			
			simul.setStep(in.nextInt());
			
			in.close();
			
			simul.getView().showStatus(simul.getStep(), field);
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
}
